import { alignX } from './utils.js';

/**
 * 表格渲染器类
 */
export class TableRenderer {
  constructor(config, columns, tableData) {
    this.config = config;
    // 使用formatColumnList计算动态列宽
    this.columns = columns;
    // 计算每列的累积宽度，用于虚拟滚动
    this.columnOffsets = this.calculateColumnOffsets();
    this.tableData = tableData;
  }

  /**
   * 计算每列的累积宽度
   */
  calculateColumnOffsets() {
    const offsets = [];
    // 注意第一个列的偏移量为 0，其他列的偏移量是前一列的偏移量加上宽度，所以一开始 0 就是起始位置，而加上列宽就是第一列的终止位置
    let currentOffset = 0;
    this.columns.forEach((column, index) => {
      offsets[index] = currentOffset;
      currentOffset += column.width;
    });
    console.log(offsets, 'offsets');
    return offsets;
  }

  /**
   * 获取列在指定滚动位置下的可见范围
   */
  getVisibleColumns(scrollLeft) {
    const startCol = this.findFirstVisibleColumn(scrollLeft);
    const endCol = this.findLastVisibleColumn(scrollLeft);
    return { startCol, endCol };
  }

  /**
   * 查找第一个可见列的索引
   */
  findFirstVisibleColumn(scrollLeft) {
    for (let i = 0; i < this.columns.length; i++) {
      if (this.columnOffsets[i] + this.columns[i].width > scrollLeft) {
        return i;
      }
    }
    return 0;
  }

  /**
   * 查找最后一个可见列的索引
   */
  findLastVisibleColumn(scrollLeft) {
    const visibleWidth = this.config.visibleWidth;
    for (let i = this.columns.length - 1; i >= 0; i--) {
      if (this.columnOffsets[i] < scrollLeft + visibleWidth) {
        return i;
      }
    }
    return this.columns.length - 1;
  }

  /**
   * 渲染表头
   */
  render_header(ctx, scrollLeft) {
    console.log(scrollLeft, 'scrollLeft');

    // 获取可见列范围
    const { startCol, endCol } = this.getVisibleColumns(scrollLeft);
    console.log(endCol, 'endCol');

    // 清空表头画布
    ctx.clearRect(0, 0, this.config.visibleWidth, this.config.headerHeight);

    // 填充表头背景
    ctx.fillStyle = '#f8f8f8';
    ctx.fillRect(0, 0, this.config.visibleWidth, this.config.headerHeight);

    // 表头文本样式
    ctx.fillStyle = '#121212';
    ctx.font = 'bold 14px Arial sans-serif';
    ctx.textBaseline = 'middle';

    // 绘制每一列的表头
    for (let col = startCol; col <= endCol; col++) {
      const column = this.columns[col];
      const x = this.columnOffsets[col] - scrollLeft;
      const align = column.align || this.config.align || 'left';

      // 设置文本对齐方式
      ctx.textAlign = align;
      ctx.lineWidth = 1;
      // 绘制文本 - 使用列定义的标题
      const text = column.label;

      ctx.fillText(
        text,
        alignX[align](x, column.width),
        this.config.headerHeight / 2
      );
    }

    // 优化批量绘制表头分隔线
    ctx.strokeStyle = '#ddd';
    ctx.beginPath();

    // 绘制边框
    if (this.config.border) {
      for (let col = startCol; col <= endCol + 1; col++) {
        if (col < this.columns.length) {
          const x = this.columnOffsets[col] - scrollLeft;
          ctx.moveTo(x, 0);
          ctx.lineTo(x, this.config.headerHeight);
        }
      }
    }

    // 底部边框
    ctx.moveTo(0, this.config.headerHeight);
    ctx.lineTo(this.config.visibleWidth, this.config.headerHeight);

    ctx.stroke();
  }

  /**
   * 获取表格总宽度
   */
  get_total_width() {
    // 根据实际列宽计算总宽度
    if (this.columns && this.columns.length > 0) {
      return (
        this.columnOffsets[this.columns.length - 1] +
        this.columns[this.columns.length - 1].width
      );
    }
    return 0;
  }

  /**
   * 获取表格总高度
   */
  get_total_height() {
    // 分段计算避免精度问题
    const rowsPerSegment = 1_000_000;
    const fullSegments = Math.floor(this.config.rows / rowsPerSegment);
    const remainingRows = this.config.rows % rowsPerSegment;

    return (
      fullSegments * rowsPerSegment * this.config.cellHeight +
      remainingRows * this.config.cellHeight +
      this.config.headerHeight
    );
  }

  /**
   * 渲染内容区域
   */
  render_content(canvasCtx, data, scrollLeft, scrollTop, startRow) {
    // 清空画布
    canvasCtx.clearRect(
      0,
      0,
      this.config.visibleWidth,
      this.config.visibleHeight
    );

    // 获取可见列范围
    const { startCol, endCol } = this.getVisibleColumns(scrollLeft);

    // 计算可见区域中的起始/结束行索引
    const visibleRows =
      Math.ceil(this.config.visibleHeight / this.config.cellHeight) + 1;
    const endRow = Math.min(startRow + visibleRows, this.config.rows - 1);

    // 绘制表格内容
    this.render_content_cells(
      canvasCtx,
      data,
      0, // 在数据数组中的起始索引是0
      Math.floor(endRow - startRow), // 数据数组的结束索引
      startCol,
      endCol,
      scrollLeft,
      scrollTop - startRow * this.config.cellHeight // 调整滚动位置
    );
  }

  /**
   * 渲染表格单元格内容
   */
  render_content_cells(
    ctx,
    data,
    dataStartRow,
    dataEndRow,
    startCol,
    endCol,
    scrollLeft,
    adjustedScrollTop
  ) {
    // 先批量绘制偶数行背景
    ctx.fillStyle = '#ffffff';
    for (let rowIdx = dataStartRow; rowIdx <= dataEndRow; rowIdx++) {
      if (rowIdx >= data.length) {
        break; // 防止访问不存在的数据
      }
      const actualRow = rowIdx;
      if (actualRow % 2 !== 0) {
        continue;
      }

      // 计算行的Y坐标
      const y = rowIdx * this.config.cellHeight - adjustedScrollTop;

      // 如果行不可见，跳过
      if (y + this.config.cellHeight < 0 || y > this.config.visibleHeight) {
        continue;
      }

      ctx.fillRect(0, y, this.config.visibleWidth, this.config.cellHeight);
    }

    // 再批量绘制奇数行背景
    ctx.fillStyle = '#f9f9f9';
    for (let rowIdx = dataStartRow; rowIdx <= dataEndRow; rowIdx++) {
      if (rowIdx >= data.length) {
        break;
      }
      const actualRow = rowIdx;
      if (actualRow % 2 === 0) {
        continue;
      }

      // 计算行的Y坐标
      const y = rowIdx * this.config.cellHeight - adjustedScrollTop;

      // 如果行不可见，跳过
      if (y + this.config.cellHeight < 0 || y > this.config.visibleHeight) {
        continue;
      }

      ctx.fillRect(0, y, this.config.visibleWidth, this.config.cellHeight);
    }

    // 绘制单元格内容
    ctx.fillStyle = '#333';
    ctx.font = '14px Arial';
    ctx.textBaseline = 'middle';

    for (let rowIdx = dataStartRow; rowIdx <= dataEndRow; rowIdx++) {
      if (rowIdx >= data.length) {
        break;
      }

      const rowData = data[rowIdx];

      // 计算行的Y坐标
      const y = rowIdx * this.config.cellHeight - adjustedScrollTop;

      // 如果行不可见，跳过
      if (y + this.config.cellHeight < 0 || y > this.config.visibleHeight) {
        continue;
      }

      for (let col = startCol; col <= endCol; col++) {
        if (col >= this.columns.length) {
          break; // 防止访问不存在的列
        }

        const column = this.columns[col];
        const x = this.columnOffsets[col] - scrollLeft;
        const align = column.align || this.config.align || 'left';

        // 如果单元格在水平方向不可见，跳过
        if (x + column.width < 0 || x > this.config.visibleWidth) {
          continue;
        }

        // 设置文本对齐方式
        ctx.textAlign = align;

        const key = `col_${col}`;
        const text = rowData[key] || '';

        // 绘制单元格文本
        ctx.fillText(
          text,
          alignX[align](x, column.width),
          y + this.config.cellHeight / 2
        );
      }
    }

    ctx.strokeStyle = '#ddd';

    // 获取实际数据长度
    const actualDataRows = data.length;

    // 对每个实际存在的单元格绘制边框
    for (let rowIdx = dataStartRow; rowIdx <= dataEndRow; rowIdx++) {
      // 如果超出实际数据范围，则跳过
      if (rowIdx >= actualDataRows) {
        break;
      }

      // 计算行的Y坐标
      const y = rowIdx * this.config.cellHeight - adjustedScrollTop;

      // 如果行不可见，跳过
      if (y + this.config.cellHeight < 0 || y > this.config.visibleHeight) {
        continue;
      }

      // 绘制行分隔线
      ctx.beginPath();
      ctx.moveTo(0, y);
      ctx.lineTo(this.config.visibleWidth, y);
      ctx.stroke();

      // 绘制列分隔线
      for (let col = startCol; col <= endCol + 1; col++) {
        if (col < this.columns.length) {
          const x = this.columnOffsets[col] - scrollLeft;
          // 确保只绘制可见区域内的分隔线
          if (x >= -1 && x <= this.config.visibleWidth + 1) {
            ctx.beginPath();
            ctx.moveTo(x, y);
            ctx.lineTo(x, y + this.config.cellHeight);
            ctx.stroke();
          }
        }
      }
    }
  }
}

/**
 * 表格管理器类
 */
export class TableManager {
  // 初始化属性
  constructor(config, columns, tableData) {
    console.log('创建表格管理器');
    this.renderer = new TableRenderer(config, columns, tableData);
    this.dataCache = new Map();
    this.segmentSize = config.segmentSize;
    this.config = config;
    this.columns = columns;
    this.tableData = tableData;
  }

  /**
   * 获取表格总宽度
   */
  get_total_width() {
    return this.renderer.get_total_width();
  }

  /**
   * 获取表格总高度
   */
  get_total_height() {
    return this.renderer.get_total_height();
  }

  /**
   * 渲染表头
   */
  render_header(ctx, scrollLeft) {
    this.renderer.render_header(ctx, scrollLeft);
  }

  /**
   * 渲染内容区域
   */
  render_content(canvasCtx, scrollLeft, scrollTop) {
    // 计算可见区域的行范围
    const startRow = Math.floor(scrollTop / this.config.cellHeight);
    const visibleRows =
      Math.ceil(this.config.visibleHeight / this.config.cellHeight) + 2;
    const endRow = Math.min(startRow + visibleRows, this.config.rows - 1);

    // 准备可见数据
    const visibleData = [];
    for (let rowIdx = startRow; rowIdx <= endRow; rowIdx++) {
      const segmentIdx = Math.floor(rowIdx / this.segmentSize);

      const segment = this.get_or_load_segment(segmentIdx, this.tableData);
      const indexInSegment = rowIdx % this.segmentSize;

      if (indexInSegment < segment.length) {
        visibleData.push(segment[indexInSegment]);
      }
    }

    // 调用渲染器的内容渲染方法
    this.renderer.render_content(
      canvasCtx,
      visibleData,
      scrollLeft,
      scrollTop,
      startRow
    );
  }

  /**
   * 加载或获取某个数据段
   */
  get_or_load_segment(segmentIndex, tableData) {
    if (!this.dataCache.has(segmentIndex)) {
      const start = segmentIndex * this.segmentSize;
      const end = Math.min(start + this.segmentSize, this.config.rows);
      const segmentData = [];
      console.log(this.columns, 'this.columns');

      for (let i = start; i < end; i++) {
        const row = {};
        for (let j = 0; j < this.config.columns; j++) {
          row[`col_${j}`] = `数据 ${i + 1}-${j + 1}`;
        }
        segmentData.push(row);
      }

      // 如果缓存过大，清理一些旧数据
      if (this.dataCache.size > 10) {
        this.clean_cache(segmentIndex);
      }
      console.log(segmentData, 'segmentData');

      this.dataCache.set(segmentIndex, segmentData);
    }

    return this.dataCache.get(segmentIndex);
  }

  /**
   * 清理缓存数据，保留当前需要的段和临近段
   */
  clean_cache(currentSegmentIndex) {
    const segmentsToRemove = [];
    for (const segmentIdx of this.dataCache.keys()) {
      // 移除距离当前段超过2的段
      if (
        segmentIdx < currentSegmentIndex - 2 ||
        segmentIdx > currentSegmentIndex + 2
      ) {
        segmentsToRemove.push(segmentIdx);
      }
    }

    // 只保留最近使用的段
    if (segmentsToRemove.length > 5) {
      for (let i = 0; i < segmentsToRemove.length - 5; i++) {
        this.dataCache.delete(segmentsToRemove[i]);
      }
    }
  }

  /**
   * 配置高DPI画布
   */
  configure_hd_canvas(canvas, ctx) {
    const devicePixelRatio = window.devicePixelRatio || 1;

    // 获取 canvas 元素的显示大小
    const displayWidth = canvas.clientWidth;
    const displayHeight = canvas.clientHeight;

    // 检查 canvas 的实际大小是否与显示大小匹配
    if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
      // 设置 canvas 的内部大小为显示大小的 DPR 倍
      canvas.width = displayWidth * devicePixelRatio;
      canvas.height = displayHeight * devicePixelRatio;

      // 将所有渲染操作缩放
      ctx.scale(devicePixelRatio, devicePixelRatio);
    }

    return devicePixelRatio;
  }
}
